package com.fita.admin.service.coupon.impl;

import com.demo2do.core.entity.exception.BusinessException;
import com.demo2do.core.entity.page.Page;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.persistence.annotation.Dao;
import com.fita.admin.dao.AgentDao;
import com.fita.admin.dao.CouponDao;
import com.fita.admin.entity.content.CouponBatchSearch;
import com.fita.admin.entity.content.CouponTemplateSearch;
import com.fita.admin.entity.content.CouponUseSearch;
import com.fita.admin.service.DataServiceImpl;
import com.fita.admin.service.coupon.CouponService;
import com.fita.entity.agent.Agent;
import com.fita.entity.coupon.*;
import com.fita.entity.coupon.stat.CouponTemplateStat;
import com.fita.entity.order.Order;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * @author LZJ
 * @param <T> 
 *
 */
@Service("couponService")
public class CouponServiceImpl<T> extends DataServiceImpl<T> implements CouponService<T> {
	
	@Dao
	private AgentDao agentDao;
    
    @Dao
    private CouponDao couponDao;

    @Autowired
    private GenericDaoSupport genericDaoSupport;
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.coupon.CouponService#listCouponTemplates(com.demo2do.core.web.resolver.Page)
     */
    public List<CouponTemplate> listCouponTemplates(Page page) {
        List<CouponTemplate> result = couponDao.listCouponTemplate(page.getBeginIndex(), page.getMaxResultRecords());
        page.with(result.size());
        page.calculate();
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.coupon.CouponService#listCouponBatches(com.demo2do.core.web.resolver.Page)
     */
    public List<CouponBatch> listCouponBatches(Page page) {
        List<CouponBatch> result = couponDao.listCouponBatch(page.getBeginIndex(), page.getMaxResultRecords());
        page.with(result.size());
        page.calculate();
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.coupon.CouponService#listCoupons(co.fitstart.common.entity.coupon.CouponBatch, com.demo2do.core.web.resolver.Page)
     */
    public List<Coupon> listCoupons(CouponBatch couponBatch, Page page) {
        List<Coupon> coupons = couponDao.listCoupon(couponBatch, page.getBeginIndex(), page.getMaxResultRecords());
        return coupons.size() > page.getEveryPage() ? coupons.subList(0, page.getEveryPage()) : coupons;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.coupon.CouponService#searchCouponTemplate(co.fitstart.admin.web.controller.coupon.CouponTemplateSearch, com.demo2do.core.web.resolver.Page)
     */
    @SuppressWarnings("unchecked")
    public List<CouponTemplate> searchCouponTemplate(CouponTemplateSearch couponTemplateSearch, Page page) {
        List<CouponTemplate> result = genericDaoSupport.searchForList(couponTemplateSearch.buildSentenceTemplate(), couponTemplateSearch.buildParameters(), page.getBeginIndex(), page.getMaxResultRecords());
       
        page.with(result.size());
        page.calculate();
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.coupon.CouponService#searchCouponBatch(co.fitstart.admin.web.controller.coupon.CouponBatchSearch, com.demo2do.core.web.resolver.Page)
     */
    @SuppressWarnings("unchecked")
    public List<CouponBatch> searchCouponBatch(CouponBatchSearch couponBatchSearch, Page page) {
        List<CouponBatch> result = genericDaoSupport.searchForList(couponBatchSearch.buildSentenceTemplate(), couponBatchSearch.buildParameters(), page.getBeginIndex(), page.getMaxResultRecords());
        page.with(result.size());
        page.calculate();
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }

    /**
     * @param couponUseSearch
     * @param page
     * @return
     */
    public List<Coupon> searchCouponUse(CouponUseSearch couponUseSearch, Page page) {
        List<Coupon> result = genericDaoSupport.searchForList(couponUseSearch.buildSentenceTemplate(), couponUseSearch.buildParameters(), page.getBeginIndex(), page.getMaxResultRecords());
        page.with(result.size());
        page.calculate();
        return result.size() > page.getEveryPage() ? result.subList(0, page.getEveryPage()) : result;
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.coupon.CouponService#createCouponTemplate(co.fitstart.common.entity.coupon.CouponTemplate, java.math.BigDecimal, java.math.BigDecimal)
     */
    public void createCouponTemplate(CouponTemplate couponTemplate, BigDecimal inputAmount, BigDecimal inputMinAmount) {
        
        // save new coupon template
        genericDaoSupport.save(couponTemplate.initialize(inputAmount, inputMinAmount));
        
        // save new coupon templdate stat
        CouponTemplateStat couponTemplateStat = new CouponTemplateStat(couponTemplate);
        genericDaoSupport.save(couponTemplateStat);
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.coupon.CouponService#createCouponBatch(co.fitstart.common.entity.coupon.CouponBatch)
     */
    public void createCouponBatch(CouponBatch couponBatch) {
        
        // 1. save couponBatch
        genericDaoSupport.save(couponBatch.initialize(couponBatch.getCouponTemplate()));
        
        // 2. search CouponTemplateStat in CouponTemplate
        Long couponTemplateId = couponBatch.getCouponTemplate().getId();
        CouponTemplateStat couponTemplateStat = couponDao.getCouponTemplateStat(couponTemplateId);
        
        // 3. update couponTemplateStat
        genericDaoSupport.update(couponTemplateStat.edit(couponBatch));
        
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.CouponService#editCouponTemplate(co.fitstart.entity.coupon.CouponTemplate, java.lang.String, java.math.BigDecimal, java.math.BigDecimal)
     */
    public void editCouponTemplate(CouponTemplate couponTemplate, String inputName, BigDecimal inputAmount,
            BigDecimal inputMinAmount) {
        
        CouponBatch couponBatch = couponDao.getCouponBatch(couponTemplate);
        
        if(couponBatch != null) {
            if(!(inputName.equals(couponTemplate.getName()))) {
                genericDaoSupport.update(couponBatch.editTemplateName(inputName));
            }
        }
        
        genericDaoSupport.update(couponTemplate.edit(inputName, inputAmount, inputMinAmount));
        
    }
    
    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.CouponService#ediCouponBatch(co.fitstart.entity.coupon.CouponBatch, co.fitstart.entity.coupon.ExpireType)
     */
    public void ediCouponBatch(CouponBatch couponBatch, ExpireType inputExpireType) {
        if(!(inputExpireType.equals(couponBatch.getExpireType()))) {
            if(inputExpireType.equals(ExpireType.FIXED_DATE)) {
                couponBatch = couponBatch.editEffectiveDays(0);
            } else if (inputExpireType.equals(ExpireType.FIXED_DAYS)) {
                couponBatch = couponBatch.editEffectiveDate();
            }
        }
        
        genericDaoSupport.update(couponBatch.editExpireType(inputExpireType));
    }

    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.ecommerce.CouponService#generateCoupon(co.fitstart.common.entity.ecommerce.coupon.CouponBatch)
     */
    public void generateCoupon(CouponBatch couponBatch) {
        
        int restCount = couponBatch.getAmount() - couponBatch.getReleaseAmount();
        
        for (int i = 0; i < restCount; i++) {
            genericDaoSupport.save(new Coupon(couponBatch));
        }
        
        genericDaoSupport.update(couponBatch.editReleaseAmount(restCount));
    }


    /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.CouponService#editCouponTemplateDescription(co.fitstart.entity.coupon.CouponTemplate, java.lang.String)
     */
    public void editCouponTemplateDescription(CouponTemplate couponTemplate, String description) {
        genericDaoSupport.update(couponTemplate.editDescription(description));
    }

	/* (non-Javadoc)
	 * @see com.fita.admin.service.coupon.CouponService#countCoupon(com.fita.entity.coupon.CouponBatch)
	 */
	public int countCoupon(CouponBatch couponBatch) {
	
		Map<String, Object> parameters  = new HashMap<>();
		parameters.put("couponBatch", couponBatch);
		
		int totals = genericDaoSupport.count("FROM Coupon WHERE batch = :couponBatch  ", parameters);
		
		return totals;
	}

	/*
	 * (non-Javadoc)
	 * @see com.fita.admin.service.coupon.CouponService#loadTemplate(java.lang.Long)
	 */
	public CouponTemplate loadTemplate(Long templateId) {
		
		CouponTemplate couponTemplate = genericDaoSupport.load(CouponTemplate.class, templateId);
		
		return couponTemplate;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.fita.admin.service.coupon.CouponService#loadCoupon(java.lang.Long)
	 */
	public Coupon loadCoupon(Long couponId) {
		
		Coupon coupon = genericDaoSupport.load(Coupon.class, couponId);
		
		return coupon;
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.fita.admin.service.coupon.CouponService#loadCoupon(java.lang.String)
	 */
	public Coupon loadCoupon(String code) {
		
		Coupon coupon = couponDao.load(code);
		
		return coupon;
	}
    
	 /*
     * (non-Javadoc)
     * @see co.fitstart.admin.service.ecommerce.CouponService#identify(co.fitstart.common.entity.ecommerce.coupon.Coupon, java.lang.String)
     */
    public void identify(Coupon coupon, String identification) {
        // 1. 匹配identification 与 user的手机号。返回user
    	
    	Agent agent = agentDao.loadAgent(identification);
    	
        
        // 将user赋给coupon的user,把页面传进来的identification参数 update给coupon
        genericDaoSupport.update(coupon.identify(agent.getId(), identification,agent.getName()));
        
        // update coupon batch's claimed count
        genericDaoSupport.update(coupon.getBatch().editClaimedAmount());
    }
    
    

	/*
     * (non-Javadoc)
     * @see com.fita.admin.service.coupon.CouponService#useCoupon(com.fita.entity.data.Coupon)
     */
    public void useCoupon(Coupon coupon) {
        if(coupon == null || !coupon.getStatus().isClaimed() || coupon.getRestDay() <= 0 ) {
            throw new BusinessException("优惠券异常");
        } else {
            genericDaoSupport.update(coupon.use());
        }
    }



    public void useCoupon(Long orderId) {

        Order order = genericDaoSupport.load(Order.class, orderId);

        //如果这张订单有绑定优惠券，将优惠券改成已使用状态
        if(order.getUserCouponId() != null){
            Coupon coupon = genericDaoSupport.load(Coupon.class, order.getUserCouponId());
            coupon.setStatus(CouponStatus.USED);
            genericDaoSupport.update(coupon);
        }




    }

    /* (non-Javadoc)
	 * @see com.fita.admin.service.coupon.CouponService#resetCoupon(com.fita.entity.order.Order)
	 */
	public void resetCoupon(Order order) {
		

		List<Coupon> coupons = couponDao.listCouponsByOrder(order);
    	
    	
    	if(CollectionUtils.isNotEmpty(coupons)) {
    		
    		for (Coupon coupon :coupons ) {
    			
    			coupon.setOrder(null);
                coupon.setStatus(CouponStatus.CLAIMED);
    			genericDaoSupport.update(coupon);
    		}    		
    	} 		
	}


    @Override
    public List<Coupon> listAllUseCoupons(Page page) {

        List<Coupon> result = couponDao.listAllUseCoupons(CouponStatus.USED,page.getBeginIndex(), page.getMaxResultRecords());
        page.with(result.size());
        page.calculate();

        return result;
    }

}
